package com.yujing.yview

import android.annotation.SuppressLint
import android.app.Activity
import android.os.Build
import android.text.Editable
import android.text.InputFilter
import android.text.InputType
import android.text.TextWatcher
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.widget.AppCompatEditText
import androidx.core.content.ContextCompat
import androidx.core.graphics.toColorInt
import com.yujing.yview.base.YBaseDialog
import com.yujing.yview.databinding.DialogNumberKeyboardBinding
import java.util.*

/**
 * 数字软键盘
 *
 * @author yujing 2019年12月17日14:04:33
 * oldChange  2025-07-21 16:07:01
 */
/*用法
//密码键盘
NumberKeyboard numberKeyboard = new NumberKeyboard(this, false, NumberKeyboard.Type.PASSWORD);
numberKeyboard.setListener(s -> {
    if ("123456".equals(s)) {
        numberKeyboard.dismiss();
        //密码正确逻辑
    } else {
        YTts.play("密码错误");
    }
});
numberKeyboard.show();

kotlin
//整数键盘
val numberKeyboard = NumberKeyboard(this, false, NumberKeyboard.Type.INT)
numberKeyboard.listener =  { s -> textView1.text = s }
numberKeyboard.show()

//小数键盘
NumberKeyboard(this, false, NumberKeyboard.Type.DOUBLE).apply {
    maxLength = 6
    listener = { s -> textView1.text = s }
    textSizeScale = 1.2F
    show()
}
//身份证键盘
val numberKeyboard = NumberKeyboard(this, false, NumberKeyboard.Type.IDCARD)
numberKeyboard.maxLength = 5
numberKeyboard.hint = "请输入身份证后5位"
numberKeyboard.initCompleteListener= { it.etContent.setHintTextColor("#BBCCDD".toColorInt()) }
numberKeyboard.listener = { s ->

}
numberKeyboard.show()

//其他自定义键盘
val numberKeyboard = NumberKeyboard(this, false, NumberKeyboard.Type.STRING)
numberKeyboard.listener = { s -> textView1.text = s }
numberKeyboard.title="完全自定义键盘"
numberKeyboard.names = arrayOf(
    "你", "好", "啊", "返回",
    "哈哈", "今天", "天气", "不错",
    "123", "456", "789", ".",
    "删除", "-", "确定"
)
numberKeyboard.inputKeYListener1 = { s ->
    if ("哈哈"==s){
        YTipsDialog(this).apply {
            title = "提示"
            content = "哈哈"
            btNameOK = "确定"
            showCancelButton = false
            setOnClickListener { dismiss() }
            show()
        }
    }
}
numberKeyboard.initCompleteListener= {
    it.etContent.setHintTextColor("#BBCCDD".toColorInt())
}
numberKeyboard.maxLength = 10
numberKeyboard.hint="限制长度10"
numberKeyboard.show()
 */
class NumberKeyboard @JvmOverloads constructor(activity: Activity, isCancelable: Boolean = true, type: Type = Type.DOUBLE) : YBaseDialog<DialogNumberKeyboardBinding>(activity, R.layout.dialog_number_keyboard, android.R.style.Theme_DeviceDefault_Dialog_NoActionBar) {
    //用户输入的类型
    enum class Type {
        STRING,  //除了不能输入点和负之外可以随便输入
        PASSWORD,  //除了不能输入点和负之外可以随便输入,显示****
        INT,  //除了不能输入点之外可以随便输入,第一位不能输入0,负只能第一位
        DOUBLE, //如果第一位是0那么第二位只能输入'.'，如果直接输入'.'前面填充0，整行只允许出现一个'.',负只能第一位
        IDCARD,  //身份证键盘
    }

    //全部按键
    lateinit var viewKeys: Array<LinearLayout>

    //全部按键名称
    lateinit var viewNames: Array<TextView>

    //全部按键提示
    lateinit var viewTips: Array<TextView>

    var deleteTimer: Timer? = null

    var maxLength = Int.MAX_VALUE //最大输入长度
    var minLength = 1 //最小输入长度

    //监听
    var listener: ((String?) -> Unit)? = null
    private val controlKeys = listOf("删除", "确定", "返回", "清空") //控制键
    var type: Type

    //名称
    var title: String? = null

    //默认字符串
    var defaultString: CharSequence? = null

    //每次按键监听
    var inputKeYListener1: ((String?) -> Unit)? = null

    //文字大小比例
    var textSizeScale: Float = 1.0F

    //初始化完成
    var initCompleteListener: ((DialogNumberKeyboardBinding) -> Unit)? = null

    //提示文字
    var hint: String? = null

    //按键名称
    var names = arrayOf(
        "7", "4", "1", "返回",
        "8", "5", "2", "0",
        "9", "6", "3", ".",
        "删除", "-", "确定"
    )

    //按键提示内容
    var tips = arrayOf(
        "", "", "", "",
        "", "", "", "",
        "", "", "", "",
        "", "", ""
    )

    constructor(activity: Activity, type: Type) : this(activity, true, type) {}

    // 构造函数，主题android.R.style.Theme_Holo_Light_Dialog_NoActionBar,Theme_DeviceDefault_Dialog_NoActionBar,Theme_Material_Dialog_NoActionBar
    init {
        cancel = isCancelable
        this.activity = activity
        this.type = type
        widthPixels = 0.45f
        heightPixels = 0.8f
        fullscreen = true
        fillColor = ContextCompat.getColor(activity, R.color.fill_background)
    }

    public override fun init() {
        //点击不弹出输入法
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) binding.etContent.showSoftInputOnFocus =
            false
        //设置最大输入长度
        binding.etContent.filters = arrayOf<InputFilter>(
            InputFilter.LengthFilter(maxLength)
        )
        binding.etContent.addTextChangedListener(watcher)
        if (defaultString != null) binding.etContent.setText(defaultString)
        if (hint != null) binding.etContent.hint = hint

        viewKeys = arrayOf(
            binding.key11, binding.key12, binding.key13, binding.key14,
            binding.key21, binding.key22, binding.key23, binding.key24,
            binding.key31, binding.key32, binding.key33, binding.key34,
            binding.key41, binding.key42, binding.key43
        )
        viewNames = arrayOf(
            binding.tv11Name, binding.tv12Name, binding.tv13Name, binding.tv14Name,
            binding.tv21Name, binding.tv22Name, binding.tv23Name, binding.tv24Name,
            binding.tv31Name, binding.tv32Name, binding.tv33Name, binding.tv34Name,
            binding.tv41Name, binding.tv42Name, binding.tv43Name
        )
        viewTips = arrayOf(
            binding.tv11Tip, binding.tv12Tip, binding.tv13Tip, binding.tv14Tip,
            binding.tv21Tip, binding.tv22Tip, binding.tv23Tip, binding.tv24Tip,
            binding.tv31Tip, binding.tv32Tip, binding.tv33Tip, binding.tv34Tip,
            binding.tv41Tip, binding.tv42Tip, binding.tv43Tip
        )

        //---------------------------缩放---------------------------
        binding.tvTitle.also { it.textSize = px2sp(it.textSize.toInt()) * textSizeScale }
        binding.tvTips.also { it.textSize = px2sp(it.textSize.toInt()) * textSizeScale }
        binding.etContent.also { it.textSize = px2sp(it.textSize.toInt()) * textSizeScale }
        for (textView in viewNames) {
            textView.also { it.textSize = px2sp(it.textSize.toInt()) * textSizeScale }
        }
        for (textView in viewTips) {
            textView.also { it.textSize = px2sp(it.textSize.toInt()) * textSizeScale }
        }
        //---------------------------缩放---------------------------
        //设置键盘类型
        when (type) {
            Type.DOUBLE -> {
                binding.tvTitle.text = if (title != null) title else "数字键盘"
                binding.etContent.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
            }

            Type.INT -> {
                binding.tvTitle.text = if (title != null) title else "整数键盘"
                binding.etContent.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_NORMAL
                names = names.map { if (it == ".") "无效" else it }.toTypedArray()
            }

            Type.STRING -> {
                binding.tvTitle.text = if (title != null) title else "文本键盘"
                binding.etContent.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
                names = names.map { if (it == "-") "清空" else it }.toTypedArray()
            }

            Type.PASSWORD -> {
                binding.tvTitle.text = if (title != null) title else "密码键盘"
                binding.etContent.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
                names = names.map { if (it == "-") "清空" else it }.toTypedArray()
            }

            Type.IDCARD -> {
                binding.tvTitle.text = if (title != null) title else "身份证键盘"
                binding.etContent.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_CLASS_TEXT
                names = names.map { if (it == ".") "X" else it }.toTypedArray()
                names = names.map { if (it == "-") "清空" else it }.toTypedArray()
            }
        }

        //命名,设置监听
        for (i in names.indices) {
            //设置名称文字
            viewNames[i].text = names[i]
            //设置提示文字
            viewTips[i].text = tips[i]
            //设置隐藏提示文字
            if (tips[i].isEmpty()) viewTips[i].visibility = View.GONE
            //设置监听，如果是控制键controlKey方法
            val key = names[i]
            //判断k是控制类还是输入类
            if (controlKeys.contains(key)) {
                controlKey(i)
            } else {
                inputKey(i)
            }
        }

        initCompleteListener?.invoke(binding)
    }

    /**
     * 控制键
     *
     * @param index 按键序号
     */
    @SuppressLint("ClickableViewAccessibility")
    private fun controlKey(index: Int) {
        val key = names[index]
        viewKeys[index].isClickable = true //设置为true才能监听到MotionEvent.ACTION_UP事件
        when (key) {
            "删除" -> {
                viewNames[index].setTextColor("#FFFF6666".toColorInt())
                viewKeys[index].setOnTouchListener { v: View, event: MotionEvent ->
                    touchEvent(v, binding.etContent, event)
                    false
                }
            }

            "确定" -> {
                viewNames[index].setTextColor("#FF00FF00".toColorInt())
                viewKeys[index].setOnClickListener { v: View? ->
                    if (listener != null) {
                        if (binding.etContent.text != null) {
                            val string = binding.etContent.text.toString()
                            if (string.isNotEmpty() && string.length >= minLength) {
                                //如果是DOUBLE类型，最后一位是'.'那么最后连接上0
                                if (type == Type.DOUBLE && "." == string.substring(string.length - 1)) {
                                    listener?.invoke(string + "0")
                                } else {
                                    listener?.invoke(string)
                                }
                                dismiss()
                            }
                        }
                    }
                }
            }

            "返回" -> {
                viewNames[index].setTextColor("#FFFF9999".toColorInt())
                viewKeys[index].setOnClickListener { v: View? -> dismiss() }
            }

            "清空" -> {
                viewKeys[index].setOnClickListener { v: View? ->
                    binding.etContent.setText("")
                }
            }
        }
    }

    /**
     * 输入键
     *
     * @param index 键序号
     */
    private fun inputKey(index: Int) {
        val key = names[index]
        if ("无效" == key) {
            viewNames[index].setTextColor("#80CCCCCC".toColorInt())
            return
        }
        //当前显示内容 + key
        viewKeys[index].setOnClickListener { v: View? ->
            val oldString = binding.etContent.text.toString()
            //设置键盘类型
            if (type == Type.DOUBLE) {
                //如输入是'.'而且字符串已经包含'.'就不添加
                if ("." == key && oldString.contains(".")) return@setOnClickListener

                //如果没有输入，第一位又输入'.',那么自动填充0
                if (oldString.isEmpty() && "." == key) {
                    binding.etContent.setText(String.format("%s%s", "0", key))
                    return@setOnClickListener
                }
                //如输入是'.',先前只输入了'-',那么自动填充-0
                if ("-" == oldString && "." == key) {
                    binding.etContent.setText(String.format("%s%s", "-0", key))
                    return@setOnClickListener
                }
                //如果只输入了一位，而且是0，那么只能输入'.',如果不是'.'就不让输入
                if (oldString.length == 1 && "0" == oldString && "." != key) {
                    return@setOnClickListener
                }
                //如果只输入了2位，而且是-0，那么只能输入'.',如果不是'.'就不让输入
                if (oldString.length == 2 && "-0" == oldString && "." != key) {
                    return@setOnClickListener
                }
                //负号只能第一个位
                if (oldString.isNotEmpty() && "-" == key) return@setOnClickListener
            } else if (type == Type.INT) {
                //int第一位不能是0
                if (oldString.isEmpty() && "0" == key) return@setOnClickListener
                //负号只能第一个位
                if (oldString.isNotEmpty() && "-" == key) return@setOnClickListener
            } else if (type == Type.STRING) {
                //不限制
            } else if (type == Type.PASSWORD) {
                //不限制
            } else if (type == Type.IDCARD) {
                //只要包含X就不允许继续输入
                if (oldString.contains("X")) return@setOnClickListener
            }
            binding.etContent.setText(String.format("%s%s", oldString, key))
            inputKeYListener1?.invoke(key)
        }
    }

    //当前输入的内容
    private fun currentInput(value: String) {}

    /**
     * 删除键长按监听
     *
     * @param v        按的view
     * @param editText 处理的view——editText
     * @param event    事件
     */
    private fun touchEvent(v: View, editText: AppCompatEditText, event: MotionEvent) {
        if (event.action == MotionEvent.ACTION_DOWN) {
            Log.d("ACTION_DOWN", "ACTION_DOWN")
            deleteTimer = Timer()
            //500毫秒后开始,每隔100毫秒执行一次
            deleteTimer?.schedule(object : TimerTask() {
                override fun run() {
                    delete(editText)
                }
            }, 500, 100)
        } else if (event.action == MotionEvent.ACTION_UP) {
            Log.d("ACTION_UP", "ACTION_UP")
            delete(editText)
            if (null != deleteTimer) {
                deleteTimer?.cancel()
                deleteTimer = null
            }
        }
    }

    //删除尾巴字符串
    private fun delete(editText: AppCompatEditText) {
        //按下
        if (editText.text != null && editText.text.toString().isNotEmpty()) {
            val content = editText.text.toString()
            activity.runOnUiThread { editText.setText(content.substring(0, content.length - 1)) }
        }
    }

    //光标移动到最后
    private val watcher: TextWatcher = object : TextWatcher {
        override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
            currentInput(s.toString())
        }

        override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
        }

        override fun afterTextChanged(s: Editable) {
            binding.etContent.setSelection(binding.etContent.length())
        }
    }
}